<?php 
/*-- Project Introduce --*/


/**
 * 控制器类 MainController 
 *
 * @access public
 */
class JJ_MainController 
	extends JCAT_Controller 
{
	/**
	 * 构造函数 
	 * 
	 * @access	protected
	 * @return	void
	 */
	protected function JJ_MainController()
	{
		// 调用父类构造函数
		$this->JCAT_Controller(__CLASS__) ;

		// 初始化文档、视图、子控制器 
		$this->Initialize() ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @static
	 * @return	JJ_MainController
	 */
	static public function GetGlobalInstance()
	{
		if( !self::$aGlobalInstance )
		{
			self::$aGlobalInstance = new JJ_MainController() ;
		}
		
		return self::$aGlobalInstance ;
	}
	
	/**
	 * 取得 当前 XMPP 连接
	 *
	 * @access	public
	 * @static
	 * @return	Jabber
	 */
	static public function GetCurrentXMPPConnect()
	{
		return self::GetGlobalInstance()->GetXMPPConnect() ;
	}

	/**
	 * 初始化文档、视图、子控制器 
	 * 
	 * @access	protected
	 * @return	void
	 */
	protected function Initialize()
	{
		//<<[UnmodifiableBlock.Start]::Message Queue::>>//
		// 消息队列
		$aMessageQueue = new JCAT_MessageQueue() ;
		JCAT_MessageDispatcher::RegisterMessageQueue($aMessageQueue,JJ_Login::MSGTYPE_FAIL) ;

		// 消息输出对象
		$aMessageQueue->AddPrinter(new JCAT_MessageGtkDialogPrinter($aMessageQueue)) ;

		$this->SetMessageQueue($aMessageQueue) ;
		//<<[UnmodifiableBlock.End]::Message Queue::>>// 			
	}
	
	/**
	 * 取得主窗口
	 *
	 * @access	public
	 * @return	JJ_MainWindow
	 */
	public function GetMainWindow()
	{
		return $this->aMainWindow ;
	}

	/**
	 * 取得聊天历史对话框
	 *
	 * @access	public
	 * @return	JJ_HistoryDialog
	 */
	public function GetSessionHistoryDialog()
	{
		return $this->aSessionHistoryDialog ;
	}
		
	/**
	 * 执行入口函数 
	 * 
	 * @access	public
	 * @param	$arrArg=array	array	参数 
	 * @return	void
	 */
	public function MainRun(array $arrArg=array())
	{
		// 开始 后台进程
		JCAT_Gtk::StartBackgroundWork(1);
		
		while (1)
		{
			// 登录
			$aLogin = new JJ_Login($this) ;
			list($this->aCurrentAccount,$this->aXMPPConn) = $aLogin->MainRun() ;
			if( $this->aCurrentAccount and $this->aXMPPConn )
			{
				$sSetting = JJ_Setting::GetGlobalInstance() ;
				
				// 显示系统托盘
				$aStatusIcon = new GtkStatusIcon() ;
				$aStatusIcon->set_from_file(ROOT_PATH.'Resource/Image/window.png') ;
				$aStatusIcon->set_tooltip( $sSetting->GetItem('/JJ','ProductName').' - '.$this->aCurrentAccount->GetUsername() ) ;
				$aStatusIcon->connect('activate',array($this,'OnStatusIconActivate')) ;
				$aStatusIcon->connect('popup-menu',array($this,'OnStatusIconPopupMenu')) ;
				
				// 聊体记录 对话框
				$this->aSessionHistoryDialog = new JJ_HistoryDialog($this,$this->aCurrentAccount) ;
			
				// 连接事件
				$this->aXMPPConn->set_handler("message_chat",$this,"OnMessageChat");
				$this->aXMPPConn->set_handler("message_groupchat",$this,"OnMessageGroupChat");
				$this->aXMPPConn->set_handler("message_headline",$this,"OnMessageHeadline");
				$this->aXMPPConn->set_handler("message_normal",$this,"OnMessageChat");
				$this->aXMPPConn->set_handler("subscribe",$this,"OnSubscribe");
	
				// 改变状态
				$this->aXMPPConn->set_presence('',JCAT_Language::Sentence('在线')) ;
				
				// 显示主对话框
				$this->aMainWindow = new JJ_MainWindow($this) ;
				$this->aMainWindow->ShowView() ;
				
				// 向服务器 请求 联系人 名单
				$this->aXMPPConn->get_roster() ;
				
				// Active Ping
				$aSetting = JJ_Setting::GetGlobalInstance() ;
				$bActivePing = $aSetting->GetItem('/JJ','ActivePing') ;
				if( $bActivePing )
				{
					$aTimer = new JCAT_Timer( $aSetting->GetItem('/JJ','ActivePingInterval') ) ;
					$aTimer->Start(array($this,'OnActivePing'),-1,$aSetting->GetItem('/JJ','ActivePingUrl')) ;
				}
				
				// 活动心跳 Heartbeat
				$aTimer = new JCAT_Timer( $aSetting->GetItem('/JJ','HeartbeatInterval') ) ;
				$aTimer->Start(array($this,'OnHeartbeat'),-1) ;

				// 检查 交谈交谈命令
				$aTimer = new JCAT_Timer( 
							$aSetting->GetItem('/JJ','CheckExternalCommandInterval')
							, $aSetting->GetItem('/JJ','CheckExternalCommandIntervalMicrosec') ) ;
				$aTimer->Start(array($this,'OnCheckCommand'),-1) ;
				
				// 主循环
				// ------------------------------------------------------
				$this->bMainLooping = true ;
				while ($this->bMainLooping)
				{
					// 间隔 0.2 秒
					usleep(200000);
					
					// 计时器: 触发所有 到时的 计时器
					JCAT_Timer::Tick() ;
					
					// 执行
					$this->aXMPPConn->loop_execute_once() ;
				}
				
				JJ::PlaySound('logout') ;
				$aStatusIcon->set_visible(false) ;
			}
			
			else 
			{
				$this->bExitApp = true ;
			}
			
			if( $this->bExitApp )
			{
				break ;
			}
		}
		
		// 结束 后台进程
		JCAT_Gtk::EndBackgroundWork();
	}

	/**
	 * 取得当前 XMLPP 连接
	 *
	 * @access	public
	 * @return	Jabber
	 */
	public function GetXMPPConnect()
	{
		return $this->aXMPPConn ;
	}
	
	/**
	 * 取得当前账号
	 *
	 * @access	public
	 * @return	JJ_Account
	 */
	public function GetCurrentAccount()
	{
		return $this->aCurrentAccount ;
	}
	
	/**
	 * 结束程序
	 *
	 * @access	public
	 * @return	void
	 */
	public function Terminate($bExitApp=true)
	{
		$this->GetMainWindow()->ShowView(false,true) ;
		$this->GetXMPPConnect()->disconnect() ;
		exit() ;
		//$this->bMainLooping = false ;
		//$this->bExitApp = $bExitApp ;
	}
	
	/**
	 * 发送消息
	 *
	 * @access	public
	 * @param	$aContact		JJ_Account
	 * @param	$sMessage		string
	 * @return	void
	 */
	public function SendMessage(JJ_Account $aContact,$sMessage)
	{
		// 声音
		// JJ::PlaySound('send') ;
		
		$aXMPPConn = $this->GetXMPPConnect() ;
		$aXMPPConn->message($aContact,'normal',NULL,$sMessage) ;
	}
	
	/**
	 * 更改密码
	 *
	 * @access	public
	 * @return	void
	 */
	public function ChangePassword()
	{
		$aChangePassword = new JJ_ChangePassword($this) ;
		$aChangePassword->MainRun() ;
	}
	
	/**
	 * 添加一名联系人
	 *
	 * @access	public
	 * @return	void
	 */
	public function AddContact($sContactAddress='',$sRequestWord='')
	{
		if( $sContactAddress )
		{
			if( isset($this->aXMPPConn->roster[strtolower($sContactAddress)]) )
			{
				JCAT_Gtk::MessageDialog(JCAT_Language::Sentence('用户（%s）已经在您的好友名单中了。',$sContactAddress)) ;
				return ;
			}
		}
		
		$aAddContact = new JJ_AddContact($this) ;
		$aAddContact->MainRun(array('ContactAddress'=>$sContactAddress,'RequestWord'=>$sRequestWord)) ;
	}
	
	/**
	 * 删除联系人
	 *
	 * @access	public
	 * @param	$sContactJID		string
	 * @return	bool
	 */
	public function RemoveContact($sContactJID)
	{
		$aRemoveContact = new JJ_RemoveContact($this) ;
		return $aRemoveContact->MainRun(array('ContactJID'=>$sContactJID)) ;
	}
	
	
	/**
	 * 查找在线用户
	 *
	 * @access	public
	 * @return	void
	 */
	public function FindOnlineUsers()
	{
		$theOnlineUsersDialog = JCAT_Singleton::GetGlobalInstance('JJ_OnlineUsersDialog',$this) ;
		$theOnlineUsersDialog->ShowView() ;
		
		if( !$theOnlineUsersDialog->IsFinding() )
		{
			$theOnlineUsersDialog->Find() ;
		}
	}
	
	/**
	 * 取得账户的临时目录
	 *
	 * @access	public
	 * @return	string
	 */
	public function GetAccountTempDir()
	{
		$sDir = ROOT_PATH.'Temp/'.$this->aCurrentAccount->GetJabberAddress().'/' ;
		if( !file_exists($sDir) )
		{
			mkdir($sDir) ;
			chmod($sDir,0777) ;
		}
		JCAT_ASSERT::ASSERT_DIR($sDir,JCAT_Language::Sentence('无法当前账户创建临时目录：“%s”',$sDir));
		return $sDir ;
	}
	
	// 消息事件 /////////////////////////////////////////////////
	/**
	 * 聊天开始
	 *
	 * @access	public
	 * @return	void
	 */
	public function OnMessageChat($sFrom,$sTo,$sBody,$sSubject,$thread,$sId,$Extended,$arrPacket)
	{
		// 不理会 空消息
		if( !$sBody )
		{
			return ;
		}
		
		$aAccount = JJ_Account::CreateFromString($sFrom) ;
		if( !$aAccount )
		{
			return ;
		}
		
		// 声音
		// JJ::PlaySound('receive');
		
		$aSessionView = JJ_SessionWindow::GetInstance($aAccount,$this) ;
		$aSessionView->ShowView() ;
		$aSessionView->DisplayMessage($aAccount,$sBody) ;
	}
	
	/**
	 * 群聊天开始
	 *
	 * @access	public
	 * @return	void
	 */
	public function OnMessageGroupChat($packet)
	{
		echo 'OnMessageGroupChat' ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @return	void
	 */
	public function OnMessageHeadline($from,$to,$body,$subject,$extended,$packet)
	{
		echo 'OnMessageHeadline' ;
	}
	
	
	/**
	 * 响应 订阅请求
	 *
	 * @access	public
	 * @return	void
	 */
	public function OnSubscribe($packet)
	{
		if( isset($packet['presence']['@']['from']) )
		{
			$aAcceptSubscribe = new JJ_AcceptSubscribe($this) ;
			var_dump($packet) ;
			$sMessage = isset($packet['presence']['#']['status'][0]['#'])?
								$packet['presence']['#']['status'][0]['#']: null ;
			$aAcceptSubscribe->MainRun(array(
						'JID'=>$packet['presence']['@']['from']
						, 'Message'=>$sMessage)) ;
		}
	}

	
	/**
	 * 响应 系统托盘 图标点击
	 *
	 * @access	public
	 * @return	void
	 */
	public function OnStatusIconActivate()
	{
		$theMainWindow = $this->GetMainWindow() ;
		$wndMainWindow = $theMainWindow->GetWidget() ;
		$wndMainWindow->set_visible( !$wndMainWindow->is_visible(), false ); 
	}
	
	/**
	 * 响应 系统托盘 图标点击
	 *
	 * @access	public
	 * @return	void
	 */
	public function OnStatusIconPopupMenu()
	{
		$theMainWindow = $this->GetMainWindow() ;
		$aCreator = $theMainWindow->GetCreator() ;
		$aMenu = $aCreator->GetWidget('MenuForStatusIcon',array('TheView'=>$theMainWindow)) ;
		$aMenu->popup();
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @param	$sPingUrl
	 * @return	void
	 */
	public function OnActivePing($sPingUrl)
	{
		$sPingUrl.= urlencode($this->aCurrentAccount->GetJabberAddress()) ;
		
		// 读取数据
		$nTry = 5 ;
		while(0<$nTry--)
		{
			$hPing = fopen($sPingUrl,'r') ;
			if($hPing!==false)
			{
				break ;
			}
		}
		if($hPing===false)
		{
			return ;
		}
		
		$sReturn = '' ;
		$arrReads = array($hPing) ;
		$arrWrites = $arrExcepts = NULL ;
		while (!feof($hPing))
		{
			$nUpdate = @stream_select($arrReads,$arrWrites,$arrExcepts,0,200) ;
			if($nUpdate>0)
			{
			  	$sReturn.= fread($hPing, 1024);
			}
		}
		fclose($hPing);
	}

	/**
	 * 活动心跳
	 *
	 * @access	public
	 * @return	void
	 */
	public function OnHeartbeat()
	{
		$sAccountDir = $this->GetAccountTempDir() ;
		
		// 写入活动时间
		file_put_contents($sAccountDir.'Heartbeat',time()) ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @return	void
	 */
	public function OnCheckCommand()
	{
		// 检查账户目录
		JJ_ExternalCommand::CheckCommand($this->GetAccountTempDir().'Command/') ;

		// 检查公共目录
		JJ_ExternalCommand::CheckCommand(ROOT_PATH.'Temp/Public/Command/') ;
	}
	
	/**
	 * Description
	 * 
	 * @access	private
	 * @var		Jabber
	 */
	private $aXMPPConn ;
	
	/**
	 * Description
	 * 
	 * @access	private
	 * @var		JJ_Account
	 */
	private $aCurrentAccount ;

	/**
	 * 主循环
	 * 
	 * @access	private
	 * @var		bool
	 */
	private $bMainLooping = false ;

	/**
	 * 退出应用程序
	 * 
	 * @access	private
	 * @var		bool
	 */
	private $bExitApp = false ;
	
	
	/**
	 * 主窗口
	 * 
	 * @access	private
	 * @var		JJ_MainWindow
	 */
	private $aMainWindow ;
	
	/**
	 * Description
	 * 
	 * @access	private
	 * @var		JJ_HistoryDialog
	 */
	private $aSessionHistoryDialog ;
	
	/**
	 * Description
	 * 
	 * @access	private
	 * @static
	 * @var		JJ_MainController
	 */
	static private $aGlobalInstance ;
}

?>